#include "xx_tool.h"
#include <WiFi.h>
#include <ESPAsyncWebServer.h>
#include <PubSubClient.h>
#include <vector>
#include <sstream>

// const char *ssid = "XIXI";
// const char *password = "XX123456..";

const char *ssid = "YK_DYNAMIC";
const char *password = "yk123456";

const char *esp_ssid = "XXESP32";        // 热点名称
const char *esp_password = "12345678XX"; // 热点密码

// 替换为您的MQTT代理地址和端口
const char *mqttServer = "8.137.99.64";
const int mqttPort = 1883;

// 替换为您的MQTT用户名和密码（如果需要）
const char *mqttUser = "zhaonx";
const char *mqttPassword = "Zhaonx123..";

// 设备类型
const char *name = "";

// 设备协议
vector<const char *> device_topics;

WiFiClient espClient;
PubSubClient client(espClient);
AsyncWebServer server(80); // 声明成员变量
String macAddress = "";

// 函数声明
void handleRoot();
void handleConnect();
// 连接到WiFi
void setupWiFi()
{
    if (isNull(ssid) || isNull(password))
    {
        log("start softAP and HTTP server");
        WiFi.softAP(esp_ssid, esp_password); // 启动ap

        // 扫描周边Wi-Fi网络
        int n = WiFi.scanNetworks();
        String options = "";
        for (int i = 0; i < n; ++i)
        {
            options += "<option value=\"";
            options += WiFi.SSID(i);
            options += "\">";
            options += WiFi.SSID(i);
            options += " (";
            options += (WiFi.encryptionType(i) == WIFI_AUTH_OPEN) ? "Open" : "Secured";
            options += ") - ";
            options += WiFi.RSSI(i);
            options += " dBm</option>";
        }

        // 创建主页路由
        server.on("/", HTTP_GET, [options](AsyncWebServerRequest *request)
                  {
            String html = "<!DOCTYPE html><html><head><title>ESP32 Config</title></head><body>"
                          "<h2>Select WiFi Network</h2>"
                            "<form action=\"/set\" method=\"post\">"
                            "<label for=\"ssid\">SSID:</label>"
                            "<select name=\"ssid\" id=\"ssid\">";
                      html += options;
                      html += "</select><br><br>"
                              "<label for=\"pass\">Password:</label>"
                              "<input type=\"password\" name=\"pass\" id=\"pass\"><br><br>"
                              "<input type=\"submit\" value=\"Submit\"></form></body></html>";
                              request->send(200, "text/html", html); });

        // 处理表单提交
        server.on("/set", HTTP_POST, [](AsyncWebServerRequest *request)
                  {

                    if (request->hasParam("ssid", true) && request->hasParam("pass", true)) {
                        String ssid = request->getParam("ssid", true)->value();
                        String pass = request->getParam("pass", true)->value();
                        ssid = ssid.c_str();
                        password = pass.c_str();
                        // 重新连接 WiFi
                        setupWiFi();
                        request->send(200, "text/plain", "Configuration updated successfully!");
                    }
            else{
                request->send(400, "text/plain", "Bad Request: Missing SSID or Password.");
            } });

        server.begin(); // 启动http服务
    }
    else
    {
        WiFi.begin(ssid, password);
        int attempts = 0;
        while (WiFi.status() != WL_CONNECTED && attempts < 30) // 等待连接或超时
        {
            delay(1000);
            log(".");
            attempts++;
        }
        if (WiFi.status() == WL_CONNECTED)
        {
            log("\nConnected to WiFi!");
            macAddress = WiFi.macAddress();
            delay(1000);
            server.end();
            WiFi.softAPdisconnect(true); // 断开 AP 热点
        }
        else
        {
            ssid = "";
            password = "";
            log("\nFailed to connect. Restarting hotspot...");
            setupWiFi(); // 重新配网
        }
    }
}

// MQTT
// 连接到MQTT代理
void (*handleReceivedMessage)(const char *, const char *) = [](const char *topic, const char *message) {}; // 接收到消息回调
void (*handleOnConnect)(const char *) = [](const char *) {};                                               // 连接成功回调

void xx_mqtt_sendMessage(const char *topic, const char *message)
{
    String fullString = String(name) + "/" + String(macAddress) + "/" + String(topic);
    Serial.println(fullString.c_str());
    Serial.println(message);
    client.publish(fullString.c_str(), message);
}

void sendMessage_p(const char *topic, const char *message) // 发送公共消息
{
    String fullString = "P/" + String(topic);
    client.publish(fullString.c_str(), message);
}

void xx_mqtt_subscribe(const char *topic)
{
    // 订阅工作消息
    client.subscribe(topic);
}

// 订阅全部内容
void subscribe_all()
{
    // 公共
    xx_mqtt_subscribe("P/S");
    for (const auto &item : device_topics)
    {
        Serial.println(item);
        String all_msg = String(name) + "/" + macAddress + "/" + item;

        Serial.println(all_msg);

        xx_mqtt_subscribe(all_msg.c_str());
    }
}

// 处理接收到的消息
void callback(char *topic, byte *payload, unsigned int length)
{
    // 消息
    String message = "";
    for (int i = 0; i < length; i++)
    {
        message += (char)payload[i];
    }

    istringstream stream(topic);
    string segment;
    vector<string> tokens;
    while(getline(stream, segment, '/')) {
        tokens.push_back(segment);
    }
    if (tokens[0] == "P") // 公共消息
    {
        if (tokens[1] == "S")
        { 
            // 协议上报
            String fullString = String(name) + "/" + macAddress;
            for (const auto &item : device_topics)
            {
                fullString += "/" + String(item);
            }
            sendMessage_p("S_A",  fullString.c_str());
        }
    }
    else
    {
        Serial.println(tokens[2].c_str());
        // 判断为此设备
        if (tokens[0] == name && tokens[1] == macAddress.c_str())
        {
            handleReceivedMessage(tokens[2].c_str(), message.c_str());
        }
    }
}

void reconnect()
{
    while (!client.connected())
    {
        log("Attempting MQTT connection...");
        if (client.connect("ESP32Client", mqttUser, mqttPassword))
        {
            log("MQTT connected");
            subscribe_all();
            handleOnConnect(macAddress.c_str());
        }
        else
        {
            log("failed, rc=");
            log(client.state());
            log(" try again in 5 seconds");
            delay(5000);
        }
    }
}

// 提供给外部的接口，用于处理接收到的消息
void xx_mqtt_setOnMessageReceived(void (*func)(const char *, const char *))
{
    handleReceivedMessage = func;
}

void xx_mqtt_setOnConnected(void (*func)(const char *))
{
    handleOnConnect = func;
}

void xx_mqtt_setup(const char *n, vector<const char*> topics)
{
    for (int i = 0; i < topics.size(); i++)
    {
        Serial.println(topics[i]);
        device_topics.push_back(topics[i]); // 将主题添加到设备主题列表
    }
    name = n;
    delay(500);
    setupWiFi(); // 配置网络
    client.setServer(mqttServer, mqttPort);
    client.setCallback(callback);
}

void xx_mqtt_loop()
{
    if (WiFi.status() == WL_CONNECTED)
    {   // 已连接
        if (!client.connected())
        {
            reconnect();
            delay(1000);
        }
        client.loop();
    }
}